package com.trailer.base.base

import android.app.Application
import androidx.databinding.Observable.OnPropertyChangedCallback
import androidx.databinding.PropertyChangeRegistry
import androidx.lifecycle.viewModelScope
import com.trailer.base.net.IResp
import com.trailer.base.utils.Toasts
import com.trailer.base.view.BRView
import kotlinx.coroutines.launch

@Suppress("UNCHECKED_CAST")
abstract class BRViewModel<R : BRRepository>(application: Application) : BViewModel<R>(application) {

    override fun toast(msg: String?) {
        Toasts.toast(view().context(), msg)
    }

    override fun toast(msgId: Int) {
        Toasts.toast(view().context(), msgId)
    }

    override fun firstReq() {
        /*如果列表里已经有数据了,请求的时候pagable=false*/

        val pagable = view().adapter().data.isEmpty()

        repository().page = 0

        viewModelScope.launch {
            repository().reqFirstPage(pagable, apiFunc())
        }

//        repository().reqFirstPage(api() as Observable<IResponse<Collection<Any>>>, pagable)
//                .subscribe()
    }


    fun reqMore() = viewModelScope.launch {
        repository().reqMore()
    }


    override fun init() {}
    override fun view(): BRView<*> {
        return bView as BRView<*>
    }

    @Transient
    private var mCallbacks: PropertyChangeRegistry? = null
    override fun addOnPropertyChangedCallback(callback: OnPropertyChangedCallback) {
        synchronized(this) {
            if (mCallbacks == null) {
                mCallbacks = PropertyChangeRegistry()
            }
        }
        mCallbacks!!.add(callback)
    }

    override fun removeOnPropertyChangedCallback(callback: OnPropertyChangedCallback) {
        synchronized(this) {
            if (mCallbacks == null) {
                return
            }
        }
        mCallbacks!!.remove(callback)
    }

    /**
     * Notifies listeners that all properties of this instance have changed.
     */
    override fun notifyChange() {
        synchronized(this) {
            if (mCallbacks == null) {
                return
            }
        }
        mCallbacks!!.notifyCallbacks(this, 0, null)
    }

    /**
     * Notifies listeners that a specific property has changed. The getter for the property
     * that changes should be marked with [Bindable] to generate a field in
     * `BR` to be used as `fieldId`.
     *
     * @param fieldId The generated BR id for the Bindable field.
     */
    override fun notifyPropertyChanged(fieldId: Int) {
        synchronized(this) {
            if (mCallbacks == null) {
                return
            }
        }
        mCallbacks!!.notifyCallbacks(this, fieldId, null)
    }

    override fun createRepository(): R {
        return BRRepository() as R
    }

//    abstract fun api(): Observable<out IResponse<*>>

    abstract fun apiFunc(): suspend () -> IResp<*>

}
